package com.example.nsddemo

import android.content.Context
import android.net.nsd.NsdManager
import android.net.nsd.NsdServiceInfo
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.net.ServerSocket
import java.net.Socket
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

/**
 * ServiceProviderActivity - 服务提供者Activity
 *
 * 该Activity负责：
 * 1. 注册NSD服务，使其他设备可以发现此服务
 * 2. 启动TCP服务器，处理客户端连接和消息通信
 * 3. 管理连接的客户端并广播消息
 */
class ServiceProviderActivity : AppCompatActivity() {

    companion object {
        // 日志标签，用于调试和错误追踪
        private const val TAG = "ServiceProvider"

        // 服务名称，其他设备将通过此名称发现服务
        private const val SERVICE_NAME = "NsdDemoService"

        // 服务类型，使用自定义类型_demo._tcp.
        // 格式为_<自定义名称>._tcp.，这是NSD标准格式
        private const val SERVICE_TYPE = "_demo._tcp."
    }

    // NSD管理器，用于注册和注销网络服务
    private lateinit var nsdManager: NsdManager

    // 服务注册监听器，处理服务注册过程中的各种事件
    private var registrationListener: NsdManager.RegistrationListener? = null

    // UI组件
    private lateinit var toggleServiceButton: Button          // 启动/停止服务按钮
    private lateinit var serviceStatusTextView: TextView     // 服务状态显示文本
    private lateinit var connectedClientsTextView: TextView  // 连接客户端列表显示文本

    // 服务状态标志
    private var isServiceRegistered = false

    // TCP服务器相关组件
    private var serverSocket: ServerSocket? = null           // 服务器Socket
    private var serverExecutor: ExecutorService? = null      // 服务器线程池

    // 客户端管理集合
    private val connectedClients = mutableMapOf<String, Socket>()     // 已连接客户端Socket映射
    private val clientOutputs = mutableMapOf<String, PrintWriter>()   // 客户端输出流映射

    /**
     * Activity创建时调用
     * 初始化UI、设置监听器、获取系统服务
     */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_service_provider)
        initViews()                         // 初始化UI组件
        setupClickListeners()               // 设置按钮点击监听器
        nsdManager = getSystemService(Context.NSD_SERVICE) as NsdManager // 获取NSD管理器系统服务
        initializeRegistrationListener()    // 初始化服务注册监听器
    }

    /**
     * 初始化UI组件
     * 获取布局中的各个控件引用
     */
    private fun initViews() {
        toggleServiceButton = findViewById(R.id.toggleServiceButton)
        serviceStatusTextView = findViewById(R.id.serviceStatusTextView)
        connectedClientsTextView = findViewById(R.id.connectedClientsTextView)

        // 初始化UI显示状态
        updateUI()
    }

    /**
     * 设置按钮点击监听器
     * 根据当前服务状态切换启动/停止服务功能
     */
    private fun setupClickListeners() {
        toggleServiceButton.setOnClickListener {
            // 如果服务已注册，则注销服务；否则注册服务
            if (isServiceRegistered) {
                unregisterService()
            } else {
                registerService()
            }
        }
    }

    /**
     * 注册NSD服务
     * 使其他设备能够通过网络发现此服务
     */
    private fun registerService() {
        // 创建服务信息对象
        val serviceInfo = NsdServiceInfo().apply {
            serviceName = SERVICE_NAME      // 设置服务名称
            serviceType = SERVICE_TYPE      // 设置服务类型
            port = 8080                     // 设置服务端口

            // 设置可选的元数据属性
            setAttribute("version", "1.0")                    // 服务版本
            setAttribute("device", android.os.Build.MODEL)    // 设备型号
        }

        try {
            // 注册服务到网络
            nsdManager.registerService(
                serviceInfo,
                NsdManager.PROTOCOL_DNS_SD,     // 使用DNS-SD协议
                registrationListener             // 注册监听器
            )
            startTcpServer() // 启动TCP服务器
            Toast.makeText(this, "正在注册服务...", Toast.LENGTH_SHORT).show()
        } catch (e: Exception) {
            Log.e(TAG, "注册服务失败", e)
            Toast.makeText(this, "注册服务失败: ${e.message}", Toast.LENGTH_SHORT).show()
        }
    }

    /**
     * 启动TCP服务器
     * 在独立线程中监听客户端连接并处理消息
     */
    private fun startTcpServer() {
        serverExecutor = Executors.newCachedThreadPool() // 创建线程池用于处理服务器操作

        serverExecutor?.execute {
            try {
                serverSocket = ServerSocket(8080) // 创建服务器Socket并绑定到8080端口
                runOnUiThread {
                    Toast.makeText(this@ServiceProviderActivity, "TCP服务器已启动", Toast.LENGTH_SHORT).show()
                    serviceStatusTextView.text = "服务状态: 运行中\n端口: 8080"
                }

                Log.d(TAG, "TCP服务器开始监听端口 8080")
                // 持续监听客户端连接
                while (!Thread.currentThread().isInterrupted) { // 检查当前线程是否已被中断
                    try {
                        val clientSocket = serverSocket?.accept() // 等待并接受客户端连接

                        clientSocket?.let { socket ->

                            val clientId = "${socket.inetAddress.hostAddress}:${socket.port}" // 生成客户端唯一标识符（IP:端口）
                            Log.d(TAG, "新客户端连接: $clientId")
                            val output = PrintWriter(socket.getOutputStream(), true) // 为客户端创建输出流

                            // 将客户端添加到管理集合中
                            connectedClients[clientId] = socket
                            clientOutputs[clientId] = output

                            // 在主线程更新UI显示新客户端
                            runOnUiThread {
                                Toast.makeText(this@ServiceProviderActivity, "新客户端连接: $clientId", Toast.LENGTH_SHORT).show()
                                updateClientList()
                            }

                            // 在新线程中处理该客户端的消息
                            serverExecutor?.execute {
                                handleClientMessages(socket, clientId)
                            }
                        }
                    } catch (e: Exception) {
                        // 只有在服务器Socket未关闭时才记录错误
                        if (serverSocket?.isClosed == false) {
                            Log.e(TAG, "接受客户端连接异常", e)
                        }
                        break  // 退出监听循环
                    }
                }
            } catch (e: Exception) {
                // 处理服务器启动异常
                Log.e(TAG, "启动TCP服务器异常", e)
                runOnUiThread {
                    Toast.makeText(this@ServiceProviderActivity, "TCP服务器启动失败: ${e.message}", Toast.LENGTH_LONG).show()
                }
            }
        }
    }

    /**
     * 处理客户端消息
     * 在独立线程中读取并处理特定客户端发送的消息
     *
     * @param socket 客户端Socket连接
     * @param clientId 客户端唯一标识符
     */
    private fun handleClientMessages(socket: Socket, clientId: String) {
        try {
            // 创建输入流读取客户端消息
            val input = BufferedReader(InputStreamReader(socket.getInputStream()))
            var message: String?

            // 持续读取消息直到连接断开
            while (true) {
                try {
                    // 读取客户端发送的一行消息
                    message = input.readLine()

                    // 如果消息为null，表示客户端已断开连接
                    if (message == null) {
                        Log.d(TAG, "客户端 $clientId 断开连接")
                        break
                    }

                    Log.d(TAG, "收到客户端 $clientId 的消息: $message")

                    // 在主线程显示收到的消息
                    runOnUiThread {
                        Toast.makeText(this@ServiceProviderActivity, "收到消息: $message", Toast.LENGTH_SHORT).show()
                    }

                    // 广播消息给所有连接的客户端
                    broadcastMessage("$clientId: $message")
                } catch (e: Exception) {
                    // 处理读取消息异常
                    Log.e(TAG, "读取客户端 $clientId 消息异常", e)
                    break  // 退出消息处理循环
                }
            }
        } catch (e: Exception) {
            // 处理处理消息过程中的异常
            Log.e(TAG, "处理客户端 $clientId 消息异常", e)
        } finally {
            // 清理客户端连接资源
            try {
                // 从管理集合中移除客户端并关闭Socket
                connectedClients.remove(clientId)?.close()
                clientOutputs.remove(clientId)

                Log.d(TAG, "客户端 $clientId 断开连接")

                // 在主线程更新客户端列表显示
                runOnUiThread {
                    updateClientList()
                }
            } catch (e: Exception) {
                // 处理关闭连接异常
                Log.e(TAG, "关闭客户端 $clientId 连接异常", e)
            }
        }
    }

    /**
     * 广播消息给所有连接的客户端
     *
     * @param message 要广播的消息内容
     */
    private fun broadcastMessage(message: String) {
        Log.d(TAG, "广播消息: $message")

        // 使用迭代器遍历所有客户端输出流
        val iterator = clientOutputs.iterator()
        while (iterator.hasNext()) {
            val entry = iterator.next()
            try {
                // 向客户端发送消息
                entry.value.println(message)
                entry.value.flush()  // 确保消息立即发送

                Log.d(TAG, "消息已发送给客户端: ${entry.key}")
            } catch (e: Exception) {
                // 处理发送消息异常
                Log.e(TAG, "向客户端 ${entry.key} 发送消息异常", e)

                // 从管理集合中移除出错的客户端
                iterator.remove()
                connectedClients.remove(entry.key)
            }
        }
    }

    /**
     * 注销NSD服务
     * 停止服务广播并清理相关资源
     */
    private fun unregisterService() {
        // 确保服务已注册且监听器存在
        if (isServiceRegistered && registrationListener != null) {
            try {
                // 注销NSD服务
                nsdManager.unregisterService(registrationListener)

                // 更新服务状态
                isServiceRegistered = false

                // 停止TCP服务器
                stopTcpServer()

                // 提示用户服务已注销
                Toast.makeText(this, "服务已注销", Toast.LENGTH_SHORT).show()
            } catch (e: Exception) {
                // 处理注销失败情况
                Log.e(TAG, "注销服务失败", e)
                Toast.makeText(this, "注销服务失败: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    /**
     * 停止TCP服务器
     * 关闭所有客户端连接并释放服务器资源
     */
    private fun stopTcpServer() {
        try {
            // 关闭服务器Socket
            serverSocket?.close()

            // 关闭所有客户端Socket连接
            connectedClients.values.forEach { socket ->
                try {
                    socket.close()
                } catch (e: Exception) {
                    Log.e(TAG, "关闭客户端socket异常", e)
                }
            }

            // 清空客户端管理集合
            connectedClients.clear()

            // 关闭所有客户端输出流
            clientOutputs.values.forEach { output ->
                try {
                    output.close()
                } catch (e: Exception) {
                    Log.e(TAG, "关闭输出流异常", e)
                }
            }

            // 清空输出流管理集合
            clientOutputs.clear()

            // 关闭线程池
            serverExecutor?.shutdown()

            // 在主线程更新UI
            runOnUiThread {
                serviceStatusTextView.text = "服务状态: 已停止"
                updateClientList()
            }
        } catch (e: Exception) {
            // 处理关闭服务器异常
            Log.e(TAG, "关闭TCP服务器异常", e)
        }
    }

    /**
     * 更新UI显示
     * 根据服务状态更新按钮文本和状态显示
     */
    private fun updateUI() {
        // 根据服务注册状态设置按钮文本
        toggleServiceButton.text = if (isServiceRegistered) "停止服务" else "启动服务"

        // 根据服务注册状态设置状态文本
        serviceStatusTextView.text = if (isServiceRegistered)
            "服务状态: 运行中\n端口: 8080"
        else
            "服务状态: 已停止"
    }

    /**
     * 更新客户端列表显示
     * 显示当前连接的所有客户端信息
     */
    private fun updateClientList() {
        // 根据客户端连接情况生成显示文本
        val clientList = if (connectedClients.isEmpty()) {
            "无连接客户端"
        } else {
            "已连接客户端:\n" + connectedClients.keys.joinToString("\n")
        }

        // 更新客户端列表显示
        connectedClientsTextView.text = clientList
    }

    /**
     * 初始化服务注册监听器
     * 处理服务注册过程中的各种回调事件
     */
    private fun initializeRegistrationListener() {
        registrationListener = object : NsdManager.RegistrationListener {
            /**
             * 服务注册成功回调
             * @param serviceInfo 已注册的服务信息
             */
            override fun onServiceRegistered(serviceInfo: NsdServiceInfo) {
                Log.d(TAG, "服务注册成功: ${serviceInfo.serviceName}")
                isServiceRegistered = true // 更新服务注册状态
                runOnUiThread {
                    updateUI()
                    Toast.makeText(this@ServiceProviderActivity, "服务注册成功!", Toast.LENGTH_SHORT).show()
                }
            }

            /**
             * 服务注册失败回调
             * @param serviceInfo 服务信息
             * @param errorCode 错误代码
             */
            override fun onRegistrationFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
                Log.e(TAG, "服务注册失败: 错误码 = $errorCode")
                runOnUiThread {
                    Toast.makeText(this@ServiceProviderActivity, "注册失败: $errorCode", Toast.LENGTH_SHORT).show()
                }
            }

            /**
             * 服务注销失败回调
             * @param serviceInfo 服务信息
             * @param errorCode 错误代码
             */
            override fun onUnregistrationFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) {
                Log.e(TAG, "服务注销失败: 错误码 = $errorCode")
                runOnUiThread {
                    Toast.makeText(this@ServiceProviderActivity, "注销失败: $errorCode", Toast.LENGTH_SHORT).show()
                }
            }

            /**
             * 服务注销成功回调
             * @param serviceInfo 已注销的服务信息
             */
            override fun onServiceUnregistered(serviceInfo: NsdServiceInfo) {
                Log.d(TAG, "服务已注销: ${serviceInfo.serviceName}")
                isServiceRegistered = false // 更新服务注册状态
                runOnUiThread {
                    updateUI()
                }
            }
        }
    }

    /**
     * Activity销毁时调用
     * 清理资源，确保服务被正确注销
     */
    override fun onDestroy() {
        super.onDestroy()

        // 如果服务仍在注册状态，则注销服务
        if (isServiceRegistered) unregisterService()
    }
}
